//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System;
using System.ComponentModel;
using System.Net;
using System.Workflow.ComponentModel;
using Microsoft.Research.ScientificWorkflow.Helper;

namespace Microsoft.Research.ScientificWorkflow.Activities
{
    /// <summary>
    /// This class executed the DAP query on the sever and read the
    /// data back from the server.
    /// This class then reads the data from the DAP data types to
    /// the Trident supported types.
    /// </summary>
    [Name("OpenDap Data Reader")]
    [Description("Executes the Open DAP query on the server, reads the data from the server and then converts them to Trident supported types.")]
    [WorkflowCategory("OpenDap")]
    class OpenDAPDataReader : Activity
    {
        #region Property Definitions

        public static DependencyProperty InputDAPUriProperty = DependencyProperty.Register("InputDAPUri",
            typeof(OpenDAPURI), typeof(OpenDAPDataReader));

        /// <summary>
        /// Input Open DAP Uri generated after appending the server name
        /// and the file name.
        /// </summary>
        [RequiredInputParam]
        [Name("Input Open DAP Uri")]
        [Description("Input Open DAP Uri for getting the data.")]
        public OpenDAPURI InputDAPUri
        {
            get { return ((OpenDAPURI)(base.GetValue(OpenDAPDataReader.InputDAPUriProperty))); }
            set { base.SetValue(OpenDAPDataReader.InputDAPUriProperty, value); }
        }

        public static DependencyProperty DataArrayProperty = DependencyProperty.Register("DataArray",
            typeof(object[]), typeof(OpenDAPDataReader));

        /// <summary>
        /// Object Array with data for the datatypes speicified in the 
        /// open dap query.
        /// </summary>
        [OutputParam]
        [Name("Data Array")]
        [Description("Array of objects with data for the variables.")]
        public object[] DataArray
        {
            get { return ((object [])(base.GetValue(OpenDAPDataReader.DataArrayProperty))); }
            set { base.SetValue(OpenDAPDataReader.DataArrayProperty, value); }
        }

        #endregion

        #region Overridden methods
        
        /// <summary>
        /// Adds the selection values to the dapuri object. To do
        /// so this class uses the querbuilder class.
        /// </summary>
        /// <param name="executionContext"></param>
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            OpenDAPUrlBuilder builder = new OpenDAPUrlBuilder(this.InputDAPUri);
            Uri query = builder.CreateQuery();
            
            string file = ".\\Temp.nc"; 
            DownloadData(file, query);

            DAPDataReader reader = new DAPDataReader(file);
            DataHolder[] data = reader.ParseDAPFile(this.InputDAPUri);

            OpenDAPDataConverter converter = new OpenDAPDataConverter();
            this.DataArray = converter.Convert(this.InputDAPUri, ref data);

            return ActivityExecutionStatus.Closed;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// This method gets the data from the srever and stores the
        /// data read to a local file.
        /// </summary>
        /// <param name="filename"></param>
        private void DownloadData(string filename, Uri query)
        {
            System.Net.WebRequest webReq = HttpWebRequest.Create(query);
            WebResponse webResp = webReq.GetResponse();
            
            System.IO.Stream stream = webResp.GetResponseStream();
            System.IO.BinaryReader br = new System.IO.BinaryReader(stream);

            System.IO.FileStream fileWriter = new System.IO.FileStream(filename, System.IO.FileMode.OpenOrCreate);
            System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fileWriter);
            
            byte[] buffer = new byte[100];
            while (true)
            {
                int read = br.Read(buffer, 0, 100);
                bw.Write(buffer);
                if (read < 100)
                    break;
            }

            bw.Close();
            fileWriter.Close();
            webResp.Close();
        }

        #endregion
    }
}
